#ifndef PLAYERH
#define PLAYERH

#include <map>
#include <gmMachine.h>
#include <gmUserObject.h>
#include <gmTableObject.h>

#include "ByteStream.h"
#include "Client.h"

enum PlayerProperty
{
    PLAYER_PROP_X,
    PLAYER_PROP_Y,
    PLAYER_PROP_RUPEES,
    PLAYER_PROP_BOMBS,
    PLAYER_PROP_DARTS,
    PLAYER_PROP_MP,
    PLAYER_PROP_AP,
    PLAYER_PROP_HEARTS,
    PLAYER_PROP_FULL_HEARTS,
    PLAYER_PROP_DIR,
    PLAYER_PROP_GLOVE_POWER,
    PLAYER_PROP_SWORD_POWER,
    PLAYER_PROP_SHIELD_POWER,
    PLAYER_PROP_BOMB_POWER,
    PLAYER_PROP_HEAD_IMAGE,
    PLAYER_PROP_BODY_IMAGE,
    PLAYER_PROP_SWORD_IMAGE,
    PLAYER_PROP_SHIELD_IMAGE,
    PLAYER_PROP_HORSE_IMAGE,
    PLAYER_PROP_HORSE_BUSHES,
    PLAYER_PROP_SPRITE,
    PLAYER_PROP_CARRY_SPRITE,
    PLAYER_PROP_ACCOUNT,
    PLAYER_PROP_NICK,
    PLAYER_PROP_ANI,
    PLAYER_PROP_CHAT,
    PLAYER_PROP_KILLS,
    PLAYER_PROP_DEATHS,
    PLAYER_PROP_ONLINE_SECS,
    PLAYER_PROP_STATUS,
    PLAYER_PROP_LEVELNAME,
    PLAYER_PROP_ENUM_SIZE,
    PLAYER_PROP_INVALID
};

class Player
{
protected:
    int m_id;
    GMClient* m_client;
    gmVariable props[PLAYER_PROP_ENUM_SIZE];

public:
    Player(int id, GMClient* client = NULL);
    //~Player();

    void SendAccount();

    void WritePacket(const ByteStream& packet) {
        if(m_client)
            m_client->WritePacket(packet);
    }

    bool ReadPacket(ByteStream* stream) {
        if(m_client)
            return m_client->ReadPacket(stream);
        return false;
    }

    int GetID() const {
        return m_id;
    }

    GMClient* GetClient() {
        return m_client;
    }

    gmVariable& GetProperty(PlayerProperty prop) {
        return props[prop];
    }

    void SetProperty(PlayerProperty prop, const gmVariable& value) {
        props[prop] = value;
    }

};

class GMPlayer:
    public Player
{
private:
    gmUserObject* m_userObject;
    gmTableObject* m_userTable;

    static gmType m_userType;
    static std::map<gmptr, PlayerProperty> m_propertyMap;
    static void AssignGMPropertyIndex(gmMachine* machine, const std::string& propName, PlayerProperty prop);
    static PlayerProperty GMGetPropertyIndex(gmptr propRef);

    static bool GM_CDECL GMTrace(gmMachine * a_machine, gmUserObject* a_object, gmGarbageCollector* a_gc, const int a_workLeftToGo, int& a_workDone);
    static void GM_CDECL GMOPDotGet(gmThread * a_thread, gmVariable * a_operands);
    static void GM_CDECL GMOPDotSet(gmThread * a_thread, gmVariable * a_operands);

public:
    GMPlayer(gmMachine* machine, int id, GMClient* client = NULL);
    ~GMPlayer();

    gmUserObject* GetUserObject() {
        return m_userObject;
    }

    static gmType GetType() {
        return m_userType;
    }

    static void Register(gmMachine* machine);

};
#endif // PLAYERH

